﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Palsta.Core
{
    /* 
     * Abstract base class of all XslElement who will need to be translated into js functions
     */
    public abstract class XslElement
    {
        #region Members
        /*
         * Static members 
         */
        protected static int _jsFunctionIndex = 0; //function index counter
        protected readonly static String _functionPrefix = "xslt_"; // js function prefix
        protected bool _canReactEvent = false;
        /*
         * Inner members  
         */
        protected String _jsFunctionName = _functionPrefix + "abstract";
        protected XslElement _xslParent;
        protected XmlNode _xmlParent;
        /*
         * Protected members
         */ 
        protected XmlNode _xmlNode; //node in xml file
        protected IList<XslElement> _xslChildNodes = new List<XslElement>(); // child nodes (xls) collection
        protected int _index = 0; // node index for instance;
        #endregion

        #region Constructors
        /*
         * Constructors
         */

        protected XslElement()
        {
        }

        public XslElement(XmlNode xslNode)
        {
            _xmlNode = xslNode;
            _jsFunctionIndex++;
            _index = _jsFunctionIndex;
        }
        #endregion

        #region Accessors
        /*
         * Accessors 
         */
        public virtual String JSFunctionName
        {
            get
            {
                return _jsFunctionName;
            }
        }

        public virtual int NodeIndex
        {
            get
            {
                return _index;
            }
        }

        public virtual bool CanReactEvent
        {
            get
            {
                return _canReactEvent;
            }
            set
            {
                _canReactEvent = value;
            }
        }

        public virtual IList<XslElement> ChildNoes
        {
            get
            {
                return _xslChildNodes;
            }
        }

        public virtual XslElement XslParent
        { 
            get
            {
                return _xslParent;
            }
            set
            {
                _xslParent = value;
            }
        }

        public virtual XmlNode XmlParent
        {
            get
            {
                return _xmlParent;
            }
            set
            {
                _xmlParent = value;
            }
        }
        #endregion

        #region Methods
        /*
         * Abstract Methods
         */
        /// <summary>
        /// this function is used to build the declaration of js function according to the xsl element entity
        /// </summary>
        public abstract String GetFunctionDeclareScript(); 

        /*
         * Pre-defined Methods
         */
        /// <summary>
        /// get the function js calling according to the xsl element entity
        /// </summary>
        public virtual String GetFunctionCallingScript()
        {
            return _jsFunctionName + "_" + _index.ToString() + "();";
        }
        /// <summary>
        /// find the html node effected by the xls element instance
        /// </summary>
        public virtual XmlNode GetHTMLRootNode()
        {
            XmlNode parent = _xmlNode.ParentNode;
            while (parent != null && parent.Name.ToLower().IndexOf("xsl:") != -1)
            {
                parent = parent.ParentNode;
            }
            if (parent.Name.ToLower().IndexOf("xsl:") == -1)
            {
                return parent;
            }
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual XslElement GetEventReactParentNode()
        {
            XslElement parent = XslParent;
            if (parent != null)
            {
                while (!parent.CanReactEvent)
                {
                    parent = parent.XslParent;
                    if (parent == null) break;
                }
                if (parent != null && !parent.CanReactEvent)
                {
                    parent = null;
                }
            }
            return parent;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected virtual XslElement GetEventReactChildNode()
        {
            XslElement node = null;
            foreach (XslElement child in ChildNoes)
            {
                if (child.CanReactEvent)
                {
                    node = child;
                    break;
                }
                else
                {
                    node = child.GetEventReactChildNode();
                }
            }
            return node;
        }
        #endregion 
    }
}
